package com.naiterui.ehp.bs.doctor.service.security.impl;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.naiterui.ehp.bp.domain.Doctor;
import com.naiterui.ehp.bp.domain.Login;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.bs.doctor.dao.IDoctorDao;
import com.naiterui.ehp.bs.doctor.dao.ILoginDao;
import com.naiterui.ehp.bs.doctor.exception.ExceptionCodes;
import com.naiterui.ehp.bs.doctor.service.security.ISecurityService;
import com.naiterui.ehp.bs.doctor.utils.PropertyValueConstants;
import com.naiterui.ehp.bs.doctor.utils.RedisUtils;

@Service
public class AdSecurityServiceImpl implements ISecurityService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdSecurityServiceImpl.class);

    @Autowired
    private IDoctorDao doctorDao;
    @Autowired
    private ILoginDao loginDao;

    /*
     * 校验token
     * ISecurityService.saveCheckToken()
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveCheckToken(Long doctorId, String token) throws IOException {

        return this.saveCheckToken(doctorId.toString(), token, null);
    }

    /*
     * 校验token-response写入异常信息
     * ISecurityService.saveCheckToken()
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveCheckToken(String doctorId, String token, HttpServletResponse response) throws IOException {

        if (!StringUtils.isNumeric(doctorId) || StringUtils.isBlank(token)) {
            this.stuffErrorCode(response, ExceptionCodes.TOLOGIN);
            return false;
        }

        // 缓存登录校验
        // 获取医生状态
        String hashKey = PropertyValueConstants.DOCTOR_ACCOUNT_KEY + doctorId;
        String fieldsKey = PropertyValueConstants.DOCTOR_STATUS_KEY;
        Object cacheStauts = RedisUtils.hmget(hashKey, fieldsKey);
        // 医生已经被禁用
        if (cacheStauts != null && cacheStauts instanceof ArrayList) {
            ArrayList list = (ArrayList) cacheStauts;
            if ((PropertyValueConstants.DOCTOR_ACCOUNT_STATUS_DISABLE + "").equals(list.get(0))) {
                // 提示用户已经被禁用
                this.stuffErrorCode(response, ExceptionCodes.DOCTOR_ACCOUNT_NOT_NOMAL);
                return false;
            }
        }

        try {
            String loginCacheKey = PropertyValueConstants.DOCTOR_LOGIN_TOKEN_KEY + doctorId;
            String cacheToken = RedisUtils.getString(loginCacheKey);
            if (token.equals(cacheToken)) {
                return true;
            }

        } catch (Exception e) {

            LOGGER.error("从redis中获取缓存用户登陆token失败,doctorId=" + doctorId, e);
        }

        // 数据库登录校验

        Doctor doctor = this.doctorDao.get(Long.parseLong(doctorId));
        if (doctor == null) {
            // 提示去登陆
            this.stuffErrorCode(response, ExceptionCodes.TOLOGIN);
            return false;
        }

        if (doctor.getAccountStatus() == PropertyValueConstants.DOCTOR_ACCOUNT_STATUS_DISABLE) {
            // 提示用户已经被禁用
            this.stuffErrorCode(response, ExceptionCodes.DOCTOR_ACCOUNT_NOT_NOMAL);
            return false;
        }

        Long loginId = doctor.getUserId();
        Login login = this.loginDao.get(loginId);
        if (login == null || !token.equals(login.getToken())) {
            // 提示去登陆
            this.stuffErrorCode(response, ExceptionCodes.TOLOGIN);
            return false;
        }

        try {
            String cacheKey = PropertyValueConstants.DOCTOR_LOGIN_TOKEN_KEY + doctorId;
            RedisUtils.set(cacheKey, token);
        } catch (Exception e) {

            LOGGER.error("向redis中缓存用户登陆token失败,doctorId=" + doctorId, e);
        }

        return true;
    }

    /**
     * SecurityServiceImpl.stuffErrorCode()
     *
     * @param response
     * @param errorCode
     *
     * @throws IOException
     * @Author mudou
     * @Date 2017年7月10日
     * @since 2.8.0
     */
    private void stuffErrorCode(HttpServletResponse response, int errorCode) throws IOException {
        if (null == response) {
            return;
        }
        response.getWriter().println(JsonMapper.toJson(PublicService.returnResponseVO(errorCode)));
    }

}
